package cuatroenraya.jugadores;

import java.util.ArrayList;
import java.math.*;
import cuatroenraya.Jugador;

public class JugadorAlumnoG9 extends Jugador {
	
	//Variable usada para almacenar el estado anterior del tablero
	private static int tableroEstatico[][];
	private static int fichaNuestra = 1;
	
	// pesos de los parametros
	// inicialisados por los valores del mejor jugador
	private int pesoProximidad=14; // alpha
	private int  pesoLineas=72; // beta
	private int pesoAgresividad=35; // gamma
	private int pesoDefensividad=43;// delta
	private int pesoConstante=22; //epsilon
	
	// METODOS //
	
	public JugadorAlumnoG9(){ //Constructor por defecto

		numeroJugador=55;
		nombre="Genetic Power";
		//Inicializacion de la variable para guardar el tablero
		tableroEstatico= new int[8][8];
		printParamJugador("Jugador Alumno");
		
	}//Fin del Constructor por defecto
	
	public JugadorAlumnoG9(
		int pesoProx,int pesoLin, int pesoAgr, int pesoDef, int pesoCste){ 
			//Constructor con inicializaci�on de pesos

		numeroJugador=55;
		nombre="Genetic Power";
		tableroEstatico= new int[8][8];
		
		pesoProximidad=pesoProx; // alpha
		pesoLineas= pesoLin; // beta
		pesoAgresividad=pesoAgr; // gamma
		pesoDefensividad=pesoDef;// delta
		pesoConstante=pesoCste; //epsilon	
			
	}// Fin del constructor con inicializaci�on de pesos
	
	
	public int[] GetParametrosDelJugador(){
		return (new int[]{pesoProximidad,
							pesoLineas,
							pesoAgresividad,
							pesoDefensividad,
							pesoConstante});
	} //Fin del Get
	
	public void printParamJugador(String nombre){
		System.out.println("Los parametros del jugador "+ nombre+ " son :");
		System.out.println("pesoProximidad = "+pesoProximidad);
		System.out.println("pesoLineas = "+pesoLineas);
		System.out.println("pesoAgresividad = "+pesoAgresividad);
		System.out.println("pesoDefensividad = "+pesoDefensividad);
		System.out.println("pesoConstante = "+pesoConstante);
		System.out.println(" ");
	} // Fin del printParamJugador
	
	public void printTablero(int[][] tablero, int i, int j){
		int fila,columna;
		String line=new String();
		for(fila=0; fila<8; fila++) {
			for(columna=0; columna<8; columna++) {
				line+=tablero[fila][columna]+ "  ";
			}
			System.out.println(line);
			line="";
		}
		System.out.println("");
	}// Fin del printTablero
	
	
	@Override	public int[] jugar(int tablero[][])
	// returna la posicion en q jugamos la ficha en este turno
    {
		int suma = 0;
		int fila,columna;
		
		// primer turno : jugamos en el medio
		for(fila=0; fila<8; fila++) {
			for(columna=0; columna<8; columna++) {
				suma+=tablero[fila][columna];	
			}
		}
		
		if(suma==0){
			int[] posicionAJugar = new int[2];
			posicionAJugar[0]=2+(int)Math.floor(Math.random()*4);
			posicionAJugar[1]=2+(int)Math.floor(Math.random()*4);
			return posicionAJugar;
		}// fin primer turno
		

		
		//Guardamos el tablero pasado en la ultima jugada
		this.tableroEstatico=tablero;
		
		// Calculamos la heuristica
		int[][] tableroHeuristica=calcularHeuristica(tablero);
		printTablero(tableroHeuristica,8,8);
		return calcularPosicionAJugar(tableroHeuristica,tablero);
		
    }// Fin del m�todo jugar
	
	
	private int[] calcularPosicionAJugar(
							int tableroHeuristica[][],int tablero[][]) {
		
		int fila,columna;
		int valorMaximo = 0;
		int i=0;
		int posiciones[][]=new int[64][2];
		
		// buscamos el valor m��ximo
		for(fila=0; fila<8; fila++) { 
			for(columna=0; columna<8; columna++) {
				if(tableroHeuristica[fila][columna]>valorMaximo){
					valorMaximo=tableroHeuristica[fila][columna];
				}
			}
		}
		
		// guardamos las posiciones q tienen el peso m�ximo
		for(fila=0; fila<8; fila++) {
			for(columna=0; columna<8; columna++) {
				if(tableroHeuristica[fila][columna]==valorMaximo){
					posiciones[i][0]=fila;
					posiciones[i][1]=columna;
					i++;
				}
			}
		}
		
		// Elegimos aleatoriamente a dentro de los posiciones con peso m�s alto
		int[] posicion = new int[2];
		posicion=posiciones[(int)Math.floor(Math.random()*(i))];

		return posicion;
	}// Fin del m�todo calcularPosicionAJugar	
	

	private int[][] calcularHeuristica(int tablero[][]){

		int tableroHeuristica[][]=new int[8][8];
		int fila,columna;
		
		for(fila=0; fila<8; fila++) {
			for(columna=0; columna<8; columna++) {
				if(tablero[fila][columna]!=0){
					tableroHeuristica=calcularHeuristicaEnUnPunto(tablero,
												tableroHeuristica,fila,columna);
				}
			}
		}
		return tableroHeuristica;
	}// Fin del m�todo calcularHeuristica
	
	
	private int[][] calcularHeuristicaEnUnPunto(int tablero[][], 
								int tableroHeuristica[][],int fila, int columna){
		//por cada ficha en el tablero de juego
		
		int valorDeFichaQueLlego=tablero[fila][columna]; // 1 si es nuestra, 2 sino
		int valorFichaDelOtro =(3-valorDeFichaQueLlego);
		
		tableroHeuristica[fila][columna]-=10000; // posicion donde esta la ficha
		
		
		ArrayList<Integer[]> posiciones = new ArrayList<Integer[]>(); 
		// posiciones : { fila ; columna; indice de linea; indice de proximidad  }
		// guarda los posiciones en que se debe agregar peso 
		// pq son lugares donde es posible hacer una linea
		// Proximidad = 3 al lado de la ficha, pues 2, pues 1
		// Linea = 1 o 2
		// Agresividad = 1 si estamos viendo la ficha nuestra, 0 sino
		// Defensividad = 0 si estamos viendo la ficha nuestra, 1 sino
		
		
		calcularHeuristicaEnUnPuntoHorizontal(
				tablero,posiciones,fila,columna,valorDeFichaQueLlego,valorFichaDelOtro);
		calcularHeuristicaEnUnPuntoVertical(
				tablero,posiciones,fila,columna,valorDeFichaQueLlego,valorFichaDelOtro);
		calcularHeuristicaEnUnPuntoDiagonalIzquierda(
				tablero,posiciones,fila,columna,valorDeFichaQueLlego,valorFichaDelOtro);
		calcularHeuristicaEnUnPuntoDiagonalDerecha(
				tablero,posiciones,fila,columna,valorDeFichaQueLlego,valorFichaDelOtro);
		
		// poniendo los pesos donde se pueden hacer lineas	
		for(Integer[] posicionASetear: posiciones){ 
			// para cada elemento de la lista posiciones
		
		// Calculo de los pesos a agregar	
			tableroHeuristica[posicionASetear[0]][posicionASetear[1]]+=
						pesoProximidad*posicionASetear[3]+
						pesoLineas*posicionASetear[2]+
						pesoAgresividad*(2-valorDeFichaQueLlego)+
						pesoDefensividad*(2-valorFichaDelOtro)+
						pesoConstante;
		}// Fin del for
		
		return tableroHeuristica;
	}// Fin del m�todo calcularHeuristicaEnUnPunto
	

	private ArrayList<Integer[]> calcularHeuristicaEnUnPuntoHorizontal(
					int tablero[][], ArrayList<Integer[]> posiciones,
					int fila, int columna, int valorDeFichaQueLlego, 
					int valorFichaDelOtro){
		
		int columnaAuxiliar; // columna q estamos evaluendo
		// lugares vacios o conteniendo fichas del mismo jugador de la q examinamos
		int cantidadLugares=1; 
		int indiceProximidad;
		int indiceLinea;

		ArrayList<Integer[]> posicionesBuffer = new ArrayList<Integer[]>();
		
		columnaAuxiliar=columna-1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer horizontal izquierda
		while (columnaAuxiliar>=0 && tablero[fila][columnaAuxiliar]!=valorFichaDelOtro 
						&& indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[fila][columnaAuxiliar]*valorFichaDelOtro)%2);
			posicionesBuffer.add(new Integer[]
								{fila,columnaAuxiliar,indiceLinea,indiceProximidad});
			columnaAuxiliar-=1;
		}// Fin del while
		
		// new Integer[]{filaAuxiliar,columnaAuxiliar}

		columnaAuxiliar=columna+1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer horizontal derecha
		while (columnaAuxiliar<=7 && tablero[fila][columnaAuxiliar]!=valorFichaDelOtro
						 && indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[fila][columnaAuxiliar]*valorFichaDelOtro)/2);
			posicionesBuffer.add(new Integer[]
								{fila,columnaAuxiliar,indiceLinea,indiceProximidad});
			columnaAuxiliar+=1;
		}
		
		if(cantidadLugares>=4){
			posiciones.addAll(posicionesBuffer);
		}
		
		return posiciones;
	}// Fin del m�todo calcularHeuristicaEnUnPuntoHorizontal
	
	
	private ArrayList<Integer[]> calcularHeuristicaEnUnPuntoVertical(
				int tablero[][] ,ArrayList<Integer[]> posiciones,
				int fila, int columna, int valorDeFichaQueLlego, 
				int valorFichaDelOtro){
		
		int filaAuxiliar; // fila q estamos evaluendo
		int cantidadLugares=1; // lugares vacios o conteniendo fichas amigas
		int indiceProximidad;
		int indiceLinea;
			
		ArrayList<Integer[]> posicionesBuffer = new ArrayList<Integer[]>();
		
		filaAuxiliar=fila-1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer vertical arriba
		while (filaAuxiliar>=0 && tablero[filaAuxiliar][columna]!=valorFichaDelOtro
						 && indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[filaAuxiliar][columna]*valorFichaDelOtro)/2);
			posicionesBuffer.add(new Integer[]
									{filaAuxiliar,columna,indiceLinea,indiceProximidad});
			filaAuxiliar-=1;
		}
		
		filaAuxiliar=fila+1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer vertical abajo
		while (filaAuxiliar<=7 && tablero[filaAuxiliar][columna]!=valorFichaDelOtro
					 && indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[filaAuxiliar][columna]*valorFichaDelOtro)/2);
			posicionesBuffer.add(new Integer[]
								{filaAuxiliar,columna,indiceLinea,indiceProximidad});
			filaAuxiliar+=1;
		}
		
		if(cantidadLugares>=4){
			posiciones.addAll(posicionesBuffer);
		}
		
		return posiciones;
	}// Fin del m�todo calcularHeuristicaEnUnPuntoVertical
	

	private ArrayList<Integer[]> calcularHeuristicaEnUnPuntoDiagonalIzquierda
					(int tablero[][] ,ArrayList<Integer[]> posiciones, 
						int fila, int columna, int valorDeFichaQueLlego, 
							int valorFichaDelOtro){
		
		int filaAuxiliar,columnaAuxiliar;// fila y columna q estamos evaluendo
		int cantidadLugares=1; // lugares vacios o conteniendo fichas amigas
		int indiceProximidad;
		int indiceLinea;
		ArrayList<Integer[]> posicionesBuffer = new ArrayList<Integer[]>();

		filaAuxiliar=fila-1;
		columnaAuxiliar=columna-1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer diagonal izquierda para arriba
		while (filaAuxiliar>=0 && columnaAuxiliar>=0 
						&& tablero[filaAuxiliar][columnaAuxiliar]!=valorFichaDelOtro 
						&& indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[filaAuxiliar][columnaAuxiliar]*valorFichaDelOtro)/2);
			posicionesBuffer.add(new Integer[]
							{filaAuxiliar,columnaAuxiliar,indiceLinea,indiceProximidad});
			filaAuxiliar-=1;
			columnaAuxiliar-=1;
		}
		

		filaAuxiliar=fila+1;
		columnaAuxiliar=columna+1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer diagonal izquierda para abajo
		while (filaAuxiliar<=7 && columnaAuxiliar<=7 
						&& tablero[filaAuxiliar][columnaAuxiliar]!=valorFichaDelOtro 
						&& indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=(tablero[filaAuxiliar][columnaAuxiliar]*valorFichaDelOtro);
			posicionesBuffer.add(new Integer[]
						{filaAuxiliar,columnaAuxiliar,indiceLinea,indiceProximidad});
			filaAuxiliar+=1;
			columnaAuxiliar+=1;
		}

		if(cantidadLugares>=4){
			posiciones.addAll(posicionesBuffer);
		}
		
		return posiciones;
	}// Fin del m�todo calcularHeuristicaEnUnPuntoDiagonalIzquierda
	

private ArrayList<Integer[]> calcularHeuristicaEnUnPuntoDiagonalDerecha(
						int tablero[][] ,ArrayList<Integer[]> posiciones,
						int fila, int columna, int valorDeFichaQueLlego, 
						int valorFichaDelOtro){
		
		int filaAuxiliar,columnaAuxiliar;// fila y columna q estamos evaluendo
		int cantidadLugares=1; // lugares vacios o conteniendo fichas amigas
		int indiceProximidad;
		int indiceLinea;
		ArrayList<Integer[]> posicionesBuffer = new ArrayList<Integer[]>();

		filaAuxiliar=fila-1;
		columnaAuxiliar=columna+1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer diagonal derecha para arriba
		while (filaAuxiliar>=0 && columnaAuxiliar<=7 
					&& tablero[filaAuxiliar][columnaAuxiliar]!=valorFichaDelOtro
					&& indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[filaAuxiliar][columnaAuxiliar]*valorFichaDelOtro)/2);
			posicionesBuffer.add(new Integer[]
						{filaAuxiliar,columnaAuxiliar,indiceLinea,indiceProximidad});
			filaAuxiliar-=1;
			columnaAuxiliar+=1;
		}
		

		filaAuxiliar=fila+1;
		columnaAuxiliar=columna-1;
		indiceProximidad=3;
		indiceLinea=0;
		//recorrer diagonal derecha para abajo
		while (columnaAuxiliar>=0 && filaAuxiliar<=7 
					&& tablero[filaAuxiliar][columnaAuxiliar]!=valorFichaDelOtro 
					&& indiceProximidad>0){
			cantidadLugares++;
			indiceProximidad--;
			indiceLinea+=((tablero[filaAuxiliar][columnaAuxiliar]*valorFichaDelOtro)/2);
			posicionesBuffer.add(new Integer[]
						{filaAuxiliar,columnaAuxiliar,indiceLinea,indiceProximidad});
			filaAuxiliar+=1;
			columnaAuxiliar-=1;
		}
		
		
		if(cantidadLugares>=4){
			posiciones.addAll(posicionesBuffer);
		}
		
		return posiciones;
	}// Fin del m�todo calcularHeuristicaEnUnPuntoDiagonalDerecha

}// Fin de la Clase JugadorAlumno
